package org.ediba.siri.core.publication.data;

import static org.hibernate.criterion.Example.create;

import java.util.Collection;
import java.util.Map;

import org.ediba.siri.core.Filter;
import org.ediba.siri.core.common.data.HibernateDomainDao;
import org.ediba.siri.core.publication.domain.PublicationNumber;
import org.hibernate.Criteria;
import org.hibernate.criterion.Conjunction;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Restrictions;
import org.hibernate.sql.JoinFragment;


public class HibernatePublicationNumberDao extends HibernateDomainDao<PublicationNumber, Integer> implements PublicationNumberDao {

	public HibernatePublicationNumberDao() {super(PublicationNumber.class);}

	@Override
	protected DetachedCriteria buildCriteria(PublicationNumber example) {
		DetachedCriteria detachedCriteria = this.buildCriteria();
		detachedCriteria.add(create(example));
		detachedCriteria.createCriteria(Filter.PUBLICATION.getProperty()).add(create(example.getPublication()));
		return detachedCriteria;
	}
	
	@Override
	protected DetachedCriteria buildCriteria(Collection<Map<Filter, Object>> filters) {
		DetachedCriteria detachedCriteria = this.buildCriteria();
		
		Disjunction or = Restrictions.disjunction();
		Conjunction and;
		
		for (Map<Filter, Object> map : filters) {
			and = Restrictions.conjunction();
			for (Map.Entry<Filter,Object> entry: map.entrySet())
				switch (entry.getKey()) {
					case PUBLICATION:	and.add(Restrictions.eq(Filter.PUBLICATION.getPropertyId(), entry.getValue()));	
					break;
					case IMAGE: 
						detachedCriteria.createAlias("actionuseds","actionused");
						and.add(Restrictions.eq("actionused.image.id", entry.getValue()));	
					break;
					case DATE:			and.add(Restrictions.eq(Filter.DATE.getProperty(), entry.getValue()));		
					break;
					case DATE_MIN:		and.add(Restrictions.ge(Filter.DATE_MIN.getProperty(), entry.getValue()));		
					break;
					case DATE_MAX:		and.add(Restrictions.le(Filter.DATE_MAX.getProperty(), entry.getValue()));		
					break;
					case NUMBER:		and.add(Restrictions.le(Filter.NUMBER.getProperty(), entry.getValue()));		
					break;
					case NUMBER_MAX:	and.add(Restrictions.le(Filter.NUMBER_MAX.getProperty(), entry.getValue()));		
					break;
					case NUMBER_MIN:	and.add(Restrictions.ge(Filter.NUMBER_MIN.getProperty(), entry.getValue()));		
					break;
					case DESCRIPTION:	and.add(Restrictions.ilike(Filter.DESCRIPTION.getProperty(),(String)entry.getValue(),MatchMode.ANYWHERE));		
					break;
					case MODEL:
						DetachedCriteria actionUsedCriteria =  detachedCriteria.createCriteria("actionuseds", JoinFragment.INNER_JOIN);
						DetachedCriteria imageCriteria =  actionUsedCriteria.createCriteria("image", JoinFragment.INNER_JOIN);
						DetachedCriteria modelCriteria =  imageCriteria.createCriteria("models", JoinFragment.INNER_JOIN);
						modelCriteria.add(Restrictions.eq("id", (Integer)entry.getValue()));	
					break;
				};
			or.add(and);
		}
		detachedCriteria.add(or);
		
		return detachedCriteria;
	}
	
	@Override
	protected DetachedCriteria buildCriteria(Map<Filter, Collection<Object>> filters) {
		DetachedCriteria detachedCriteria = this.buildCriteria();
		Disjunction or;
		Conjunction and = Restrictions.conjunction();
		
		for (Map.Entry<Filter,Collection<Object>> filter : filters.entrySet()){
			or = Restrictions.disjunction();
			for (Object value : filter.getValue())
				switch (filter.getKey()) {
				case ID:
					or.add(Restrictions.idEq((Integer)value));
				break;
				case PUBLICATION:
					or.add(Restrictions.eq(Filter.PUBLICATION.getPropertyId(),(Integer)value));
				break;
				case NUMBERSTR:
					or.add(Restrictions.ilike(Filter.NUMBERSTR.getProperty(), (String)value,MatchMode.START));
				break;
				}
			and.add(or);
		}
		detachedCriteria.add(and);
		detachedCriteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
		return detachedCriteria;
	}
}
